<script setup lang="ts">
import type { FormInstance, FormItemRule, FormRules, TableInstance } from 'element-plus'
import type { SysDict } from '@/apis/system/sysDictApi'
import { computed, onMounted, reactive, ref } from 'vue'
import { CommonStates } from '@/apis/common/commonApi'
import { sysDictApi } from '@/apis/system/sysDictApi'
import { hasAnyAuth } from '@/utils/authUtil'

const { root } = defineProps<{
  root: SysDict
}>()

const treeData = ref<SysDict[]>([])
const editData = ref<SysDict>()
const treeRef = ref<TableInstance>()

const rules = reactive<FormRules <Omit<SysDict, 'children'>>> ({
  dictName: [
    { required: true, message: '请输入字典名称', trigger: 'blur' },
    { min: 2, max: 64, message: '字典名称长度必须 2～64', trigger: 'blur' },

  ],
  dictCode: [
    { required: true, message: '请输入字典编码', trigger: 'blur' },
    { min: 2, max: 64, message: '编码名称长度必须 2～64', trigger: 'blur' },
  ],
  state: [
    { required: true, message: '请选择字典状态', trigger: 'blur' },
  ],
})

const customRule = computed(() => {
  const rules: FormRules = {}
  root.customFields?.forEach((f) => {
    const list: FormItemRule[] = []
    if (f.type !== 'BOOLEAN' && (f.nullable === undefined || f.nullable === false)) {
      list.push({ required: true, message: `请输入${f.title}`, trigger: 'blur' })
    }
    if (f.type === 'NUMBER') {
      list.push({ type: 'number', message: `${f.title}必须是数字`, trigger: 'blur' })
    }
    if (f.type === 'BOOLEAN') {
      list.push({ type: 'boolean', message: `${f.title}必须是数字`, trigger: 'blur' })
    }
    if (list.length > 0) {
      // rules[f.name!] = list
    }
  })
  return rules
})

onMounted(() => {
  reloadChildren(root.id!)
})

function onCreate(parent?: SysDict) {
  const createData: SysDict = {
    state: 'ENABLE',
    priority: 1,
    parentId: (parent ?? root).id,
    level: (parent ?? root).level! + 1,
    customData: (root.valueType === 'CUSTOM') ? {} : undefined,
  }
  if (parent) {
    if (parent.children === undefined) {
      parent.children = []
    }
    parent.children.splice(0, 0, createData)
    treeRef.value?.updateKeyChildren(`${parent.parentId}`, parent.children)
  }
  else {
    treeData.value.splice(0, 0, createData)
  }
  editData.value = createData
}

const rowEditFormRef = ref<FormInstance>()
async function onSaveEdit(row: SysDict) {
  rowEditFormRef.value?.validate(async (valid: boolean) => {
    if (valid) {
      let result: SysDict
      if (row.id !== -1 && row.id !== undefined) {
        result = await sysDictApi.modify(row)
        ElMessage.success('编辑字典成功')
      }
      else {
        result = await sysDictApi.create(row)
        ElMessage.success('创建字典成功')
      }
      editData.value = undefined
      await reloadChildren(result.parentId!)
    }
  })
}

async function reloadChildren(parentId: number) {
  if (parentId === root.id) {
    treeData.value = await sysDictApi.queryTree(parentId).then(list => list.filter(i => i !== undefined))
  }
  else {
    const data = await sysDictApi.queryChildren(parentId).then(list => list.filter(i => i !== undefined))
    const parent = findById(treeData.value, parentId)
    if (parent !== undefined) {
      parent.children = data
    }
  }
}

async function onRemove(row: SysDict) {
  ElMessageBox.confirm(
    '确认是否删除?',
    '请确认',
    {
      type: 'warning',
    },
  )
    .then(async () => {
      const data = await sysDictApi.remove(row.id!)
      ElMessage.success('删除字典成功')
      await reloadChildren(data.parentId!)
    })
}

async function onChangeState(row: SysDict) {
  const data = await sysDictApi.modify({ id: row.id!, state: row.state === 'DISABLE' ? 'ENABLE' : 'DISABLE' })
  ElMessage.success(`${row.state === 'DISABLE' ? '启用' : '禁用'}字典成功`)
  await reloadChildren(data.parentId!)
}

async function onCancelEdit(row: SysDict) {
  editData.value = undefined
  await reloadChildren(row.parentId!)
}

function findById(children: SysDict[], id: number): SysDict | undefined {
  for (let i = 0; i < children.length; i++) {
    const child = children[i]
    if (child.id === id) {
      return child
    }
    else if (child.children && child.children.length > 0) {
      const result = findById(child.children, id)
      if (result !== undefined) {
        return result
      }
    }
  }
}
</script>

<template>
  <div class="mb-2 flex flex-row justify-between">
    <div class="text-lg">
      {{ root.dictName }}【{{ root.dictCode }}】
    </div>
    <div>
      <el-button v-if="hasAnyAuth(`system:settings:dict:create`)" type="primary" :disabled="editData !== undefined" @click="onCreate()">
        新增
      </el-button>
      <el-button type="success" :disabled="editData !== undefined" @click="reloadChildren(root.id!)">
        刷新
      </el-button>
    </div>
  </div>

  <el-form ref="rowEditFormRef" :model="editData" :rules="rules">
    <el-table
      ref="treeRef"
      :data="treeData"
      row-key="id"
      show-overflow-tooltip stripe default-expand-all
      border
    >
      <el-table-column type="index" label="#" fixed="left" align="center" />
      <el-table-column prop="dictName" label="名称" min-width="200" fixed="left">
        <template #default="{ row }">
          <el-form-item v-if="editData?.id === row.id" prop="dictName" class="el-form-item-first">
            <el-input v-model="row.dictName" clearable />
          </el-form-item>
          <template v-else>
            {{ row.dictName }}
          </template>
        </template>
      </el-table-column>
      <el-table-column prop="dictCode" label="编码" min-width="120" fixed="left">
        <template #default="{ row }">
          <el-form-item v-if="editData?.id === row.id" prop="dictCode">
            <el-input v-model="row.dictCode" clearable />
          </el-form-item>
          <template v-else>
            {{ row.dictCode }}
          </template>
        </template>
      </el-table-column>

      <el-table-column v-if="root.valueType === 'STRING'" prop="dictValue" label="字典值" align="center" width="120">
        <template #default="{ row }">
          <el-form-item v-if="editData?.id === row.id" prop="dictValue">
            <el-input v-model="row.dictValue" clearable />
          </el-form-item>
          <template v-else>
            {{ row.dictValue }}
          </template>
        </template>
      </el-table-column>
      <template v-if="root.valueType === 'CUSTOM' && root.customFields ">
        <el-table-column v-for="f in root.customFields" :key="f.name" :prop="f.name" :label="f.title">
          <template #default="{ row }">
            <template v-if="row.customData">
              <el-form-item v-if="editData?.id === row.id" :prop="`customData.${f.name}`" :rules="customRule[f.name!]">
                <el-switch v-if="f.type === 'BOOLEAN'" v-model="row.customData[f.name!]" />
                <el-input v-if="f.type === 'NUMBER'" v-model.number="row.customData[f.name!]" clearable />
                <el-input v-if="f.type === 'STRING'" v-model.trim="row.customData[f.name!]" clearable />
              </el-form-item>
              <template v-else>
                <template v-if="f.type === 'BOOLEAN'">
                  {{ row.customData[f.name!] ? '是' : '否' }}
                </template>
                <template v-else>
                  {{ row.customData[f.name!] }}
                </template>
              </template>
            </template>
          </template>
        </el-table-column>
      </template>
      <el-table-column prop="state" label="状态" align="center" width="100">
        <template #default="{ row }">
          <el-form-item v-if="editData?.id === row.id" prop="state">
            <el-select v-model="row.state">
              <el-option v-for="(item, index) in CommonStates" :key="index" :label="item.label" :value="item.value" />
            </el-select>
          </el-form-item>
          <template v-else>
            <template v-for="(item, index) in CommonStates" :key="index">
              <el-tag v-if="item.value === row.state" :type="item.tagType">
                {{ item.label }}
              </el-tag>
            </template>
          </template>
        </template>
      </el-table-column>
      <el-table-column prop="priority" label="优先级" align="center" width="100">
        <template #default="{ row }">
          <el-form-item v-if="editData?.id === row.id" prop="priority">
            <el-input-number v-model="row.priority" />
          </el-form-item>
        </template>
      </el-table-column>
      <el-table-column v-if="hasAnyAuth('system:settings:dict:modify', 'system:settings:dict:remove', 'system:settings:dict:create')" label="操作" min-width="150" fixed="right">
        <template #default="{ row }">
          <el-button v-if="editData?.id !== row.id && hasAnyAuth(`system:settings:dict:modify`)" link type="warning" :disabled="editData !== undefined" @click="onChangeState(row)">
            {{ row.state === 'DISABLE' ? '启用' : '禁用' }}
          </el-button>
          <el-button v-if="editData?.id !== row.id && hasAnyAuth(`system:settings:remove`)" link type="danger" :disabled="editData !== undefined" @click="onRemove(row)">
            删除
          </el-button>
          <el-button v-if="editData?.id !== row.id && hasAnyAuth(`system:settings:modify`)" link type="primary" :disabled="editData !== undefined" @click="editData = row">
            编辑
          </el-button>
          <el-button v-if="editData?.id !== row.id && row.level < root.maxLevel! && hasAnyAuth(`system:settings:create`)" link type="primary" :disabled="editData !== undefined" @click="onCreate(row)">
            添加下级
          </el-button>

          <el-button v-if="editData?.id === row.id" link type="primary" @click="onSaveEdit(row)">
            保存
          </el-button>
          <el-button v-if="editData?.id === row.id" link type="info" @click="onCancelEdit(row)">
            取消
          </el-button>
        </template>
      </el-table-column>
    </el-table>
  </el-form>
</template>

<style scoped>
.el-table .el-form-item {
  margin-bottom: 0px;
}
.el-table .el-form-item-first {
  display: inline-block;
}
.el-button + .el-button {
  margin-left: 4px;
}
</style>
